﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace JasLib.Threading
{
    /// <summary>
    /// http://blogs.msdn.com/b/pfxteam/archive/2012/02/11/10266930.aspx
    /// JAS: I modified this class to allow the count to rise or fall at will,
    /// and only to signal when the count is at zero (or un-signal if it should rise above zero once again!).
    /// </summary>
    public class AsyncCountdownEvent
    {
        private readonly AsyncManualResetEvent _manualResetEvent = null;

        private volatile int _iCurrentCount = 0;
        public int CurrentCount
        {
            get { return _iCurrentCount; }
        }

        public AsyncCountdownEvent()
        {
            _iCurrentCount = 0;
            _manualResetEvent = new AsyncManualResetEvent(true);
            return;
        }

        public AsyncCountdownEvent(int _iInitialCount)
        {
            if (_iInitialCount <= 0)
                throw new ArgumentOutOfRangeException("initialCount");

            _iCurrentCount = _iInitialCount;
            _manualResetEvent = new AsyncManualResetEvent(false);
            return;
        }

        public Task WaitAsync()
        {
            return _manualResetEvent.WaitAsync();
        }

        public void AddCount(int iAdjustment)
        {
            /// Once you screw up, you're gone.
            if (_iCurrentCount < 0)
                throw new InvalidOperationException();

            int newCount = Interlocked.Add(ref _iCurrentCount, iAdjustment);
            if (newCount == 0)
                _manualResetEvent.Set();
            else if (newCount < 0)
                throw new InvalidOperationException();
            else if (newCount > 0)
                _manualResetEvent.Reset();
            return;
        }

        public void Signal()
        {
            AddCount(-1);
            return;
        }
    }
}